package com.excel.read;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.db.ColumnInfoBean;
import com.db.ForeignKey;
import com.db.sql.Node;
import com.db.sql.SqlLeafNode;
import com.db.sql.SqlNode;
import com.excel.read.GridSearchTable.OP;


public class FormTable extends GridTable {
	/**
	 * 数据库字段
	 */
	int codeIndex = -1;
	/**
	 * 表单字段
	 */
	int fieldIndex = -1;
	/**
	 * 列表显示名
	 */
	int displayNameIndex = -1;
	
	/**
	 * 是否显示
	 */
	int displayIndex = -1;
	
	
	/**
	 * 是否可查询
	 */
	int searchIndex = -1;
	
	/**
	 * 隐藏字段
	 */
	int hiddenIndex = -1;
	
	int widthIndex = -1;

	
	/**
	 * 左
	 */
    int vNameIndex = -1;
    
    
    int vTypeIndex = -1;

    int vDriveIndex = -1;
    
    /**
     * 根节点缓存
     */
    private SqlNode sqlNode;
    
    /**
     * 从全局链表中找到给定变量名的一条链,取得节点分支,分支缓存
     */
    private Map<String, List<Node>> linkMap = new HashMap<String, List<Node>> ();
    
    /**
     * 本表字段缓存
     */
    private Map<String, String> selfMap = new HashMap<String, String> ();
    
    /**
     * 子表字段缓存
     */
    private Map<String, String> childMap = new HashMap<String, String> ();
    private List<String> varNameList = new ArrayList<String>();
    private List<String> fieldNameList = new ArrayList<String>();
    
    
	/**
	 * 取得显示的数据库字段名
	 * 
	 * @return
	 */
	public String[] getCodeNameFields() {
		List<String> aList = new ArrayList();
		for (int i = 1; i < this.data.length; i++) {
			String value = this.data[i][codeIndex];
			String hiddenValue = this.data[i][hiddenIndex];
			if (hiddenValue == null || !hiddenValue.trim().equalsIgnoreCase("Y")) {
				if (value == null || value.equals("")) {
					aList.add("");
				} else {
					aList.add(this.data[i][codeIndex]);
				}
			}

		}
		String result[] = new String[aList.size()]; 
		for(int i=0; i<aList.size(); i++) {
			result[i] = aList.get(i);
		}
		return result;
	}

	/**
	 * 取得显示字段显示名List
	 * 
	 * @return
	 */
	public String[] getDisplayNameFields() {
		List<String> aList = new ArrayList();
		for (int i = 1; i < this.data.length; i++) {
			String value = this.data[i][displayNameIndex];
			String hiddenValue = this.data[i][hiddenIndex];
			if (hiddenValue == null || !hiddenValue.trim().equalsIgnoreCase("Y")) {
				if (value == null || value.equals("")) {
					aList.add("");
				} else {
					aList.add(this.data[i][displayNameIndex]);
				}
			}

		}
		String result[] = new String[aList.size()]; 
		for(int i=0; i<aList.size(); i++) {
			result[i] = aList.get(i);
		}
		return result;
	}

	/**
	 * 取得查询字段显示名List
	 * 
	 * @return
	 */
	public String[] getQueryNameFields() {
		List<String> aList = new ArrayList();
		for (int i = 1; i < this.data.length; i++) {
			String value = this.data[i][searchIndex];			
			if (value != null && value.trim().equalsIgnoreCase("N")) {
				
			}else {
				aList.add(this.data[i][vNameIndex]);
			}

		}
		String result[] = new String[aList.size()]; 
		for(int i=0; i<aList.size(); i++) {
			result[i] = aList.get(i);
		}
		return result;
	}
	
	
	
	/**
	 * 表单显示字段名List
	 * 
	 * @return
	 */
	public String[] getFieldNameFields() {
		List<String> aList = new ArrayList();
		for (int i = 1; i < this.data.length; i++) {
			String value = this.data[i][fieldIndex];
			String hiddenValue = this.data[i][hiddenIndex];
			if (hiddenValue == null || !hiddenValue.trim().equalsIgnoreCase("Y")) {
				if (value == null || value.equals("")) {
					aList.add("");
				} else {
					aList.add(this.data[i][fieldIndex]);
				}
			}

		}
		
		String result[] = new String[aList.size()]; 
		for(int i=0; i<aList.size(); i++) {
			result[i] = aList.get(i);
		}
		return result;
	}
	
	/**
	 * 一下是隐藏字段相关列表
	 */
	/**
	 * 取得隐藏的数据库字段名
	 * 
	 * @return
	 */
	public String[] getHiddenCodeNameFields() {
		List<String> aList = new ArrayList();
		for (int i = 1; i < this.data.length; i++) {
			String value = this.data[i][codeIndex];
			String hiddenValue = this.data[i][hiddenIndex];
			if (hiddenValue != null && hiddenValue.trim().equalsIgnoreCase("Y")) {
				if (value == null || value.equals("")) {
					aList.add("");
				} else {
					aList.add(this.data[i][codeIndex]);
				}
			}

		}
		String result[] = new String[aList.size()]; 
		for(int i=0; i<aList.size(); i++) {
			result[i] = aList.get(i);
		}
		return result;
	}

	/**
	 * 取得隐藏字段显示名List
	 * 
	 * @return
	 */
	public String[] getHiddenDisplayNameFields() {
		List<String> aList = new ArrayList();
		for (int i = 1; i < this.data.length; i++) {
			String value = this.data[i][displayNameIndex];
			String hiddenValue = this.data[i][hiddenIndex];
			if (hiddenValue != null && hiddenValue.trim().equalsIgnoreCase("Y")) {
				if (value == null || value.equals("")) {
					aList.add("");
				} else {
					aList.add(this.data[i][displayNameIndex]);
				}
			}

		}
		String result[] = new String[aList.size()]; 
		for(int i=0; i<aList.size(); i++) {
			result[i] = aList.get(i);
		}
		return result;
	}

	/**
	 * 表单隐藏字段名List
	 * 
	 * @return
	 */
	public String[] getHiddenFieldNameFields() {
		List<String> aList = new ArrayList();
		for (int i = 1; i < this.data.length; i++) {
			String value = this.data[i][fieldIndex];
			String hiddenValue = this.data[i][hiddenIndex];
			if (hiddenValue != null && hiddenValue.trim().equalsIgnoreCase("Y")) {
				if (value == null || value.equals("")) {
					aList.add("");
				} else {
					aList.add(this.data[i][fieldIndex]);
				}
			}

		}
		String result[] = new String[aList.size()]; 
		for(int i=0; i<aList.size(); i++) {
			result[i] = aList.get(i);
		}
		return result;
	}



	class OP{
		String nodeName;
		String opType;
		int index;
	}
	
	/**
	 * 根据节点名得到节点,找不到就添加
	 * @param nodeName:外键
	 * @param node
	 * @return
	 */
	public SqlNode getNode(String nodeName , SqlNode node) {
		SqlNode sqlNode = null;
		AllTable allTable = Config.allTable;		
		//表
		DBTable dbTable = (DBTable) allTable.get(node.getNodeName());
		//查找外键对应的表
		ForeignKey fk = dbTable.getFK(nodeName);
		DBTable toTable = fk.getToTable();
		SqlNode next = node.getNext(nodeName);
		sqlNode = next;
		//没有就添加
		if(next == null) {
			next = new SqlNode();
			next.setNodeName(toTable.name);			
			node.putNext(nodeName, next);	
			node.setTable(dbTable);
		}
		sqlNode = next;
		return sqlNode;
	}
	
	/**
	 * 根据节点名得到节点,找不到就添加
	 * @param nodeName:外键
	 * @param node
	 * @return
	 */
	public SqlNode getChildNode(String tableName ,  SqlNode node) {
		SqlNode sqlNode = null;
		AllTable allTable = Config.allTable;		
		//父表
		DBTable dbTable = (DBTable) allTable.get(node.getNodeName());
		//字表
		DBTable childTable = (DBTable) allTable.get(tableName);
		
		//查找字表外键
		//ForeignKey fk = childTable.getFK(tableName);
		//DBTable toTable = fk.getToTable();
		SqlNode prev = node.getPrev();
		sqlNode = prev;
		//没有就添加
		if(prev == null) {
			prev = new SqlNode();
			prev.setNodeName(childTable.name);			
			node.setPrev(prev);	
			node.setTable(dbTable);
		}
		sqlNode = prev;
		return sqlNode;
	}
	
	/**
	 * 根据path解析Node,
	 * 包括设置next，和prev
	 */
	public void parsePath(String path, String varName, String displayName, SqlNode root, String vType, String method) {
		String nodes[] = null;
		int index = 0;
		String flag = "";
		int totalLevel = 0;
		String firstChar = path.substring(0,1);
		String fullPath = "";
		if(firstChar.equals(".") || firstChar.equals("<")) {
			if(firstChar.equals("<")) {
				fullPath = path;
			}else {
				fullPath = path;
			}
		}else {
			fullPath = "."+path;
		}
	    
		OP op = null;
		List <OP> flagList = new ArrayList<OP>();
		List<OP> opList = new ArrayList<OP> ();
		for(int i=0; i<fullPath.length(); i++) {
			flag = fullPath.substring(i, i+1);			
			if(flag.equals(".") || flag.equals("<")) {
				totalLevel++;
				op = new OP();
				op.index = i;
				op.opType = flag;
				flagList.add(op);
			}
		}
		
		
		//单级属性
		if(totalLevel==1) {
			SqlLeafNode sqlLeafNode = new SqlLeafNode();
			sqlLeafNode.setFullPath(fullPath);
			sqlLeafNode.setNodeName(path);
			sqlLeafNode.setEntity(root);
			sqlLeafNode.setUniqName(varName);
			sqlLeafNode.setDisplayName(displayName);
			sqlLeafNode.setType(vType);
			root.putLeaf(varName, sqlLeafNode);
			
			
			
			return;
			
		}else if(totalLevel>1) {
		//多表关联	
			for(int i=0; i<flagList.size(); i++) {
				OP op2 = flagList.get(i);
				int index2 = 0;
				if(i == flagList.size()-1) {
					index2 = fullPath.length();
				}else {
					OP op3 =  flagList.get(i+1);
					index2 = op3.index;
				}
				String nodeName = fullPath.substring(op2.index+1, index2);
				op2.nodeName = nodeName;
			}
			
		}else{
		//异常
		}
		
		//当前节点
		SqlNode curNode = root;
		SqlNode oldNode = root;
		//实体节点
		for(int i=0; i<flagList.size()-1; i++) {
			OP op3 = flagList.get(i);
			String nodeName = op3.nodeName;
			String type = op3.opType;
			//深度搜索
			SqlNode next = null;
			if(type.equals(".")) {
				next = getNode(nodeName, curNode);
			}else {
				next = getChildNode(nodeName, curNode);
			}
			
			//子
			oldNode = curNode;
			//父
			curNode = next;
			
		}
		//属性节点
		OP op3 = flagList.get(flagList.size()-1);
		String atrName = op3.nodeName;
		SqlLeafNode  sqlLeafNode = new SqlLeafNode();
		sqlLeafNode.setEntity(curNode);
		sqlLeafNode.setFullPath(fullPath);
		sqlLeafNode.setNodeName(atrName);		
		sqlLeafNode.setUniqName(varName);
		sqlLeafNode.setDisplayName(displayName);
		sqlLeafNode.setType(vType);
		
		if(flagList.size()==2) {
			//根据method设置驱动器,如果method为空，设置驱动方式为文本框方式
			//否则根据method查找，得到指定的驱动器
			
			
		}else {
			
		}
		curNode.putLeaf(varName, sqlLeafNode);		
		
	}
	
	public boolean isChild(String path) {
		boolean flag = false;
		String firstChar = path.substring(0,1);
		if(firstChar.equals("<")) {
			flag = true;
		}		
		return flag;
		
	}
	/**
	 * @功能
	 * 从全局链表中找到给定变量名的一条链,取得节点分支
	 * @param path
	 * 全路径
	 * @param varName
	 * 叶子几点的变量名
	 * @param root
	 * 该表的主节点
	 * @return
	 * 节点分支链
	 */
	public String getFieldName(String path) {
	
		
		String nodes[] = null;
		int index = 0;
		String flag = "";
		int totalLevel = 0;
		String firstChar = path.substring(0,1);
		String fullPath = "";
		if(firstChar.equals(".") || firstChar.equals("<")) {	
			fullPath = path;
		}else {
			fullPath = "."+path;
		}
	    int secondIndex = -1;	
		for(int i=0; i<fullPath.length(); i++) {
			flag = fullPath.substring(i, i+1);			
			if(flag.equals(".") || flag.equals("<")) {
				totalLevel++;
				if(totalLevel == 2) {
					secondIndex = i;
					break;
				}
			}
		}
		if(secondIndex == -1) {
			secondIndex = fullPath.length();
		}
		return path.substring(1,secondIndex);
	}
	
	/**
	 * @功能
	 * 从全局链表中找到给定变量名的一条链,取得节点分支
	 * @param path
	 * 全路径
	 * @param varName
	 * 叶子几点的变量名
	 * @param root
	 * 该表的主节点
	 * @return
	 * 节点分支链
	 */
	public List<Node> getSqlNode(String path, String varName, SqlNode root) {
		List<Node> list = linkMap.get(varName);
		if(list != null) {
			return list;
		}
		list = new ArrayList<Node>();
		String nodes[] = null;
		int index = 0;
		String flag = "";
		int totalLevel = 0;
		String firstChar = path.substring(0,1);
		String fullPath = "";
		if(firstChar.equals(".") || firstChar.equals("<")) {	
			fullPath = path;
		}else {
			fullPath = "."+path;
		}
	    
		OP op = null;
		List <OP> flagList = new ArrayList<OP>();
		List<OP> opList = new ArrayList<OP> ();
		for(int i=0; i<fullPath.length(); i++) {
			flag = fullPath.substring(i, i+1);			
			if(flag.equals(".") || flag.equals("<")) {
				totalLevel++;
				op = new OP();
				op.index = i;
				op.opType = flag;
				flagList.add(op);
			}
		}
		
		String fieldName = this.getFieldName(fullPath);
		//单级属性
		if(totalLevel==1) {
			SqlLeafNode sqlLeafNode = root.getLeaf(varName);
			list.add(sqlLeafNode);
			
			//缓存字段名,只执行一次！！！！！！
			if(!this.isChild(fullPath)) {
				varNameList.add(varName);
				fieldNameList.add(fieldName);
				selfMap.put(varName, fieldName);
			}else {
				varNameList.add(varName);			
				childMap.put(varName, fieldName);
			}
			return list;
			
			
		}else if(totalLevel>1) {
		//多表关联	
			for(int i=0; i<flagList.size(); i++) {
				OP op2 = flagList.get(i);
				int index2 = 0;
				if(i == flagList.size()-1) {
					index2 = fullPath.length();
				}else {
					OP op3 =  flagList.get(i+1);
					index2 = op3.index;
				}
				String nodeName = fullPath.substring(op2.index+1, index2);
				op2.nodeName = nodeName;
			}
			
		}else{
		//异常
		}
		
		//当前节点
		SqlNode curNode = root;
		list.add(curNode);
		//实体节点
		for(int i=0; i<flagList.size()-1; i++) {
			OP op3 = flagList.get(i);
			String nodeName = op3.nodeName;
			String type = op3.opType;
			//深度搜索
			SqlNode next = null;
			if(type.equals(".")) {
				next = getNode(nodeName, curNode);
			}else {
				next = getChildNode(nodeName, curNode);
			}
			curNode = next;
			list.add(curNode);
		}
		//属性节点
		OP op3 = flagList.get(flagList.size()-1);
		String atrName = op3.nodeName;
		SqlLeafNode  sqlLeafNode = curNode.getLeaf(varName);			
		list.add(sqlLeafNode);
		
		
		linkMap.put(varName, list);
		
		//缓存字段名,只执行一次！！！！！！
		if(!this.isChild(fullPath)) {
			varNameList.add(varName);
			fieldNameList.add(fieldName);
			selfMap.put(varName, fieldName);
		}else {
			varNameList.add(varName);			
			childMap.put(varName, fieldName);
		}
		
		
		return list;
	}
	
	/**
	 * 取得查询树，并且返回根节点,
	 * 至关重要，用于语句的生成，表单的生成
	 */
	public SqlNode getRoot() {
		if(this.sqlNode != null) {
			return sqlNode;
		}
		AllTable allTable  = Config.allTable;
		DBTable dbTable = (DBTable) allTable.get(this.name);
		//根节点
		this.sqlNode = new SqlNode();
		sqlNode.setNodeName(dbTable.name);
		
		for(int i=1; i<this.data.length; i++) {
			String path = this.data[i][codeIndex];
			String displayName = this.data[i][displayNameIndex];
			String varName = this.data[i][vNameIndex];
			String vType =  this.data[i][vTypeIndex];
			String method = this.data[i][vDriveIndex];
			parsePath(path, varName, displayName, sqlNode, vType, method);
			//SqlNode
		}
		return sqlNode;
		
	}
	
	
	/**
	 * 名字，值对
	 * @return
	 */
	public Map getFullNameVaue() {
		Map<String, String> aMap = new HashMap();		
		for(int i=1; i<this.data.length; i++) {
			String path = this.data[i][codeIndex];
			
			String firstChar = path.substring(0,1);
			String fullPath = "";
			if(firstChar.equals(".") || firstChar.equals("<")) {
				fullPath = path;
			}else {
				fullPath = "."+path;
			}			
			String nodeName = this.data[i][displayNameIndex];
			String varName = this.data[i][vNameIndex];			
			aMap.put(varName, fullPath);
		}
		
		return aMap;		
	}
	

	/**
	 * MySQL SQL生成
	 * @return
	 */
	public String getInsertSQL(List<String> nameList) {
		StringBuffer sbf = new StringBuffer();
		StringBuffer sbf2= new StringBuffer();
		sbf.append("insert into "+this.name+"(");
		int i = 0;
		for(String fieldName : nameList) {
			i++;
			if(i==1) {
				sbf2.append("?");
				sbf.append(fieldName);
			}else {
				sbf.append(", "+fieldName);
				sbf2.append(",?");
			}
		}
		sbf.append(")values(");
		sbf.append(sbf2);
		sbf.append(")");
		return sbf.toString();
	}

	/**
	 * MySQL SQL生成
	 * @return
	 */
	public String getUpdateSQL(List<String> nameList) {
		StringBuffer sbf = new StringBuffer();
		StringBuffer sbf2= new StringBuffer();
		sbf.append("update "+this.name+" set ");
		int i = 0;
		for(String fieldName : nameList) {
			i++;
			if(i==1) {			
				sbf.append(fieldName + "=?");
			}else {
				sbf.append(", "+fieldName + "=?");				
			}
		}
		ColumnInfoBean pkBean = Config.getPKBean(this.name);
		sbf.append(" where "+pkBean.getName()+" = ?");	
		return sbf.toString();
	}
	
	
	/**
	 * MySQL SQL生成
	 * @return
	 */
	public String getQuerySQL(List<String> selfNameList, String pk) {
		StringBuffer sbf = new StringBuffer();
		//判断主键是否存在
//		if(selfNameList.contains(pk)) {
//			
//		}else {
//			selfNameList.add(pk);
//		}
		
		sbf.append("select ");
		String field = selfNameList.get(0);
		sbf.append(field);
		for(int i=1; i<selfNameList.size(); i++) {
			field = selfNameList.get(i);
			sbf.append(", "+field);
		}
		sbf.append(" from "+this.name+" where "+pk+"=?");
		return sbf.toString();
	}
	
	public int getVNameIndex() {
		return vNameIndex;
	}

	public void setVNameIndex(int nameIndex) {
		vNameIndex = nameIndex;
	}

	public int getVDriveIndex() {
		return vDriveIndex;
	}

	public void setVDriveIndex(int driveIndex) {
		vDriveIndex = driveIndex;
	}

	public SqlNode getSqlNode() {
		return sqlNode;
	}

	public void setSqlNode(SqlNode sqlNode) {
		this.sqlNode = sqlNode;
	}

	public Map<String, String> getSelfMap() {
		return selfMap;
	}

	public void setSelfMap(Map<String, String> selfMap) {
		this.selfMap = selfMap;
	}

	public Map<String, String> getChildMap() {
		return childMap;
	}

	public void setChildMap(Map<String, String> childMap) {
		this.childMap = childMap;
	}

	public List<String> getVarNameList() {
		return varNameList;
	}

	public void setVarNameList(List<String> varNameList) {
		this.varNameList = varNameList;
	}

	public List<String> getFieldNameList() {
		return fieldNameList;
	}

	public void setFieldNameList(List<String> fieldNameList) {
		this.fieldNameList = fieldNameList;
	}
	
	
	
	
}
